/**
 * 
 */
package sg.edu.nus.iss.vmcs.payment;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Dialog;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.util.Observable;

import sg.edu.nus.iss.vmcs.system.Fault;
import sg.edu.nus.iss.vmcs.system.FaultObserver;
import sg.edu.nus.iss.vmcs.util.LabelledDisplay;
import sg.edu.nus.iss.vmcs.util.Log;
import sg.edu.nus.iss.vmcs.util.WarningDisplay;

/**
 * @author moe
 *
 */
public class PaymentPanel extends Dialog implements FaultObserver {

	private static final String TITLE = "VMCS - Payment Panel";
	private static final String HEADING = "Payment";
	
	private PaymentController ctrl = null;
	
	private Button terminateButton;
	private WarningDisplay noChangeAvailableDisplay;
	private WarningDisplay falseCoin;
	private LabelledDisplay totalMoneyInsertedDisplay;
	private LabelledDisplay refundChangeTrayDisplay;
	private CoinInputBox coinInputBox;
	private NetsUI netsUi;
	
	public PaymentPanel(Frame fr, PaymentController ctrl) {
		super(fr, TITLE, false);
		observeFault(Fault.getInstance());
		CoinReceiver coinReceiver = ctrl.getCoinPayment().getCoinReceiver();
		this.ctrl = ctrl;

		Panel northPanel = new Panel();
		northPanel.setLayout(new GridLayout(0, 1));

		Label heading = new Label(HEADING);
		heading.setFont(new Font("Helvetica", Font.BOLD, 24));
		northPanel.add(heading);
		
		netsUi = new NetsUI(northPanel, ctrl.getNetsPayment().getNetsReader());
		northPanel.add(netsUi);

		/**
		 * Center
		 */
		Panel centerPanel = new Panel();
		centerPanel.setLayout(new GridLayout(0, 1));
		
		coinInputBox = new CoinInputBox(northPanel, coinReceiver);
		centerPanel.add(coinInputBox);

		falseCoin = new WarningDisplay("        Invalid Coin        ");
		centerPanel.add(falseCoin);
		
		// Total money inserted display
		totalMoneyInsertedDisplay = new LabelledDisplay("Total Money Insert:",
				5, LabelledDisplay.FLOW);
		totalMoneyInsertedDisplay.setEditable(false);
		totalMoneyInsertedDisplay.setValue("0 c");
		centerPanel.add(totalMoneyInsertedDisplay);

		/**
		 * South part
		 */
		Panel southPanel = new Panel();
		southPanel.setLayout(new GridLayout(0, 1));

		// No change display warning display
		noChangeAvailableDisplay = new WarningDisplay("No Change Available");
		southPanel.add(noChangeAvailableDisplay);

		// Refund/change collection display
		refundChangeTrayDisplay = new LabelledDisplay("Collect Coins:", 10,
				LabelledDisplay.FLOW);
		refundChangeTrayDisplay.setEditable(false);
		refundChangeTrayDisplay.setValue("0 c");
		southPanel.add(refundChangeTrayDisplay);

		/*
		 * Add parts to dialog box
		 */
		this.setLayout(new BorderLayout());
		this.add("North", northPanel);
		this.add("Center", centerPanel);
		this.add("South", southPanel);

		pack();
		setLocation(450, 10);
	}
	
	public void closeDown() {
		this.dispose();
	}

	public void display() {
		this.setVisible(true);
	}

	public void setStateNoChangeAvailableDisplay(boolean b) {
		noChangeAvailableDisplay.setState(b);
	}

	public void setStateInvalidCoinDisplay(boolean b) {
		Log.LogIt("-----CustomerPanel.setStateInvalidCoinDisplay:" + b );
		falseCoin.setText("Invalid Coin");
		falseCoin.setState(b);
	}

	public void showFault(Fault fault) {
		Boolean hasErr = true;
		switch (fault.getState()) {
		case NO_FAULT:
			falseCoin.setText("Invalid Coin");
			hasErr = false;
			break;
		case DispenseFault:
			falseCoin.setText("Dispense Fault");
			break;
		case ChangeGiverFault:
			falseCoin.setText("Change Giver Fault");
			break;
		case CoinReceiverFault:
			falseCoin.setText("Coin Receiver Fault");
			break;
		default:
			break;
		}
		falseCoin.setState(hasErr);
	}

	public void setValueTotalMoneyInsertedDisplay(int vl) {
		totalMoneyInsertedDisplay.setValue(vl + " c");
	}

	public void setValueRefundChangeTrayDisplay(String string) {

		refundChangeTrayDisplay.setValue(string + " c");
	}

	public CoinInputBox getCoinInputBox() {
		return coinInputBox;
	}

	public NetsUI getNetsUI(){
		return netsUi;
	}
	
	public void setStateTerminateButton(boolean b) {
		terminateButton.setEnabled(b);
	}

	public void observeFault(Fault fault) {
		Log.LogIt("CustomerPanel.ObserveFault:" + fault.getState());
		fault.addObserver(this);		
	}

	public void update(Observable arg0, Object arg1) {
		try {
			Fault fault = (Fault) arg0;
			Log.LogIt("CustomerPanel.update:" + fault.getState());
			showFault(fault);
		} catch (Exception e) {
			e.printStackTrace();
		}		
	}
	
	public void startPayment(){
		setValueTotalMoneyInsertedDisplay(0);
		setValueRefundChangeTrayDisplay("0");
	}

}
